package wangwenjun.phase2.concurrencypattern.future;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import util.ThreadUtil;

import java.util.concurrent.TimeUnit;

/**
 * @author ChangLiang
 * @date 2020/6/15
 */
@Slf4j
public class AppTest {

    @Test
    @DisplayName("test no return value")
    public void test() throws InterruptedException {
        // 定义不需要返回值的FutureService
        FutureServiceFactory<Void, Void> service = FutureServiceFactory.newService();

        service.submit(() -> {
            ThreadUtil.sleepForMilliSeconds(5_000);
            log.info("Thread:{} runnable is finished", Thread.currentThread());
        });

        log.info("Thread:{} no block", Thread.currentThread());

        Thread.currentThread().join();
    }

    @Test
    @DisplayName("test having return value, and getOutput block main thread")
    public void test2() throws InterruptedException {
        FutureServiceFactory<String, Integer> service = FutureServiceFactory.newService();
        // main线程直接执行，返回future = new FutureImpl<>()
        Future<Integer> future = service.submit(input -> {
            log.info("Thread:{} Task is started", Thread.currentThread());
            ThreadUtil.sleepForMilliSeconds(5_000);
            log.info("Thread:{} Task is finished", Thread.currentThread());
            return input.length();
        }, "hello", null);
        // 注意这里是future.get() 在这里main线程调用了future#get 进waiting状态
        log.info("Thread:{} block, result:{}", Thread.currentThread(), future.get());
    }

    @Test
    @DisplayName("test having return value, and do callback")
    public void test3(){
        FutureServiceFactory<String, Integer> service = FutureServiceFactory.newService();
        // main线程直接执行，返回future = new FutureImpl<>()
        Future<Integer> future = service.submit(input -> {
            log.info("Thread:{} Task is started", Thread.currentThread());
            ThreadUtil.sleepForMilliSeconds(5_000);
            log.info("Thread:{} Task is finished", Thread.currentThread());
            return input.length();
        }, "hello", System.out::println);

        // 主线程还是要等一下 但是可以不调用future.get进入阻塞
        // 当然在JDK中的Future提供了future.get(2,TimeUnit.SECONDS) 我们自己实现的Future没有提供这个方法
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
